import pygame
import random
import os
import math

# 初始化Pygame
pygame.init()

# 确保中文正常显示
pygame.font.init()
try:
    font = pygame.font.Font("simhei.ttf", 24)  # 尝试加载系统中的黑体字
except:
    # 如果找不到指定字体，使用默认字体
    font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC"], 24)

# 游戏窗口设置
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 720
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("羊了个羊")

# 颜色定义
BG_COLOR = (255, 255, 255)

# 卡片尺寸和间距
CARD_WIDTH = 55
CARD_HEIGHT = 70
SPACING = 30

# 游戏区域布局
GRID_ROWS = 4
GRID_COLS = 4
grid_width = GRID_COLS * (CARD_WIDTH + SPACING) - SPACING
GRID_LEFT = (SCREEN_WIDTH - grid_width) // 2
GRID_TOP = 100

# 槽位区域设置
SLOT_ROWS = 1
SLOT_COLS = 7  # 最多存放7个卡片
slot_width = SLOT_COLS * (CARD_WIDTH + 5) - 5
SLOT_LEFT = (SCREEN_WIDTH - slot_width) // 2
SLOT_TOP = SCREEN_HEIGHT - CARD_HEIGHT - 50
SLOT_HEIGHT = CARD_HEIGHT + 20

# 消除特效参数
ELIM_ANIM_DURATION = 30  # 消除动画持续帧数
elim_cards = []  # 存储正在消除的卡片信息

# 粒子特效参数
PARTICLE_COUNT = 20  # 每次消除产生的粒子数量
PARTICLE_SPEED = 3  # 粒子初始速度
PARTICLE_SIZE = 3  # 粒子大小
PARTICLE_LIFE = 30  # 粒子生命周期
particles = []  # 存储所有活动粒子

# 音效初始化
pygame.mixer.init()
try:
    elim_sound = pygame.mixer.Sound('elim_sound.wav')
except:
    print("消除音效加载失败")
    elim_sound = None

# 加载背景图像
try:
    image_folder = os.path.join(os.path.dirname(__file__), "image")
    background_path = os.path.join(image_folder, "back.png")
    background_img = pygame.image.load(background_path)
    background_img = pygame.transform.scale(background_img, (SCREEN_WIDTH, SCREEN_HEIGHT))
    print("主背景图像加载成功")
except Exception as e:
    print(f"主背景图像加载失败: {e}")
    background_img = None

# 加载槽位背景图像
try:
    slot_bg_path = os.path.join(image_folder, "back2.png")
    slot_bg_img = pygame.image.load(slot_bg_path)
    slot_bg_img = pygame.transform.scale(slot_bg_img, (slot_width + 20, SLOT_HEIGHT + 20))
    print("槽位背景图像加载成功")
except Exception as e:
    print(f"槽位背景图像加载失败: {e}")
    slot_bg_img = None

# 加载卡片图片
card_images = []
try:
    for i in range(5):
        if i == 0:
            tile_path = os.path.join(image_folder, "tile.png")
        else:
            tile_path = os.path.join(image_folder, f"tile{i}.png")

        if os.path.exists(tile_path):
            img = pygame.image.load(tile_path)
            img = pygame.transform.scale(img, (CARD_WIDTH, CARD_HEIGHT))
            card_images.append(img)
            print(f"卡片图片 {os.path.basename(tile_path)} 加载成功")
        else:
            print(f"卡片图片 {tile_path} 不存在")

    if not card_images:
        raise Exception("没有找到任何卡片图片")

except Exception as e:
    print(f"卡片图片加载失败: {e}")
    COLORS = [
        (255, 0, 0),  # 红
        (0, 255, 0),  # 绿
        (0, 0, 255),  # 蓝
        (255, 255, 0),  # 黄
        (128, 0, 128),  # 紫
    ]
    # 为粒子效果创建对应的浅色版本
    PARTICLE_COLORS = [
        (255, 150, 150),  # 浅红
        (150, 255, 150),  # 浅绿
        (150, 150, 255),  # 浅蓝
        (255, 255, 150),  # 浅黄
        (200, 150, 200),  # 浅紫
    ]

# 游戏状态
slots = []
score = 0
game_over = False
game_won = False
prop_used = False  # 道具是否已使用

# 动画相关变量
moving_card = None
moving_card_x = 0
moving_card_y = 0
target_x = 0
target_y = 0
move_speed = 10
is_moving = False  # 新增标志位，用于判断是否正在移动

# 道具按钮设置
BUTTON_WIDTH = 120
BUTTON_HEIGHT = 40
BUTTON_X = SCREEN_WIDTH - BUTTON_WIDTH - 20
BUTTON_Y = 20
BUTTON_COLOR = (0, 128, 255)
BUTTON_HOVER_COLOR = (0, 150, 255)
button_hover = False

# 特效文字
combo_text = None
combo_timer = 0


def check_victory():
    """检查是否胜利"""
    for row in grid:
        for stack in row:
            if len(stack) > 0:
                return False
    return len(slots) == 0


def create_particles(x, y, card_type):
    """创建消除粒子效果"""
    global particles

    # 获取卡片对应的颜色
    if card_images:
        # 如果有图像，使用预设的粒子颜色
        color_idx = card_type % len(PARTICLE_COLORS) if 'PARTICLE_COLORS' in globals() else 0
        color = PARTICLE_COLORS[color_idx] if 'PARTICLE_COLORS' in globals() else (255, 255, 255)
    else:
        # 如果使用纯色卡片，直接使用卡片颜色
        color = COLORS[card_type]

    # 创建粒子
    for _ in range(PARTICLE_COUNT):
        angle = random.uniform(0, 2 * math.pi)
        speed = random.uniform(0.5, PARTICLE_SPEED)
        size = random.randint(PARTICLE_SIZE - 1, PARTICLE_SIZE + 1)
        life = random.randint(PARTICLE_LIFE - 10, PARTICLE_LIFE)

        particles.append({
            'x': x + CARD_WIDTH // 2,
            'y': y + CARD_HEIGHT // 2,
            'vx': math.cos(angle) * speed,
            'vy': math.sin(angle) * speed,
            'size': size,
            'color': color,
            'life': life,
            'max_life': life
        })


def add_elim_effect(x, y, card_type):
    """添加卡片消除特效"""
    elim_cards.append({
        'x': x,
        'y': y,
        'card_type': card_type,
        'alpha': 255,  # 初始不透明度
        'frames_left': ELIM_ANIM_DURATION
    })

    # 创建粒子效果
    create_particles(x, y, card_type)

    # 播放消除音效
    if elim_sound:
        elim_sound.play()


def update_elim_effects():
    """更新消除特效状态"""
    global elim_cards
    new_elim_cards = []
    for card in elim_cards:
        card['frames_left'] -= 1
        card['alpha'] = int(255 * card['frames_left'] / ELIM_ANIM_DURATION)
        if card['frames_left'] > 0:
            new_elim_cards.append(card)
    elim_cards = new_elim_cards


def update_particles():
    """更新粒子状态"""
    global particles
    new_particles = []
    for p in particles:
        p['x'] += p['vx']
        p['y'] += p['vy']
        p['life'] -= 1

        # 粒子重力和阻力效果
        p['vy'] += 0.05  # 重力
        p['vx'] *= 0.98  # 水平阻力
        p['vy'] *= 0.98  # 垂直阻力

        if p['life'] > 0:
            new_particles.append(p)
    particles = new_particles


def draw_elim_effects():
    """绘制消除特效"""
    for card in elim_cards:
        if card_images:
            # 创建临时表面并设置透明度
            temp_surf = card_images[card['card_type']].copy()
            temp_surf.set_alpha(card['alpha'])
            screen.blit(temp_surf, (card['x'], card['y']))
        else:
            # 如果没有图像，使用带透明度的矩形
            s = pygame.Surface((CARD_WIDTH, CARD_HEIGHT), pygame.SRCALPHA)
            s.fill(COLORS[card['card_type']] + (card['alpha'],))
            screen.blit(s, (card['x'], card['y']))


def draw_particles():
    """绘制所有粒子"""
    for p in particles:
        # 计算透明度（生命周期结束时淡出）
        alpha = int(255 * p['life'] / p['max_life'])
        color = p['color'] + (alpha,)

        # 绘制粒子
        s = pygame.Surface((p['size'] * 2, p['size'] * 2), pygame.SRCALPHA)
        pygame.draw.circle(s, color, (p['size'], p['size']), p['size'])
        screen.blit(s, (p['x'] - p['size'], p['y'] - p['size']))


def draw_combo_text():
    """绘制连击文字"""
    global combo_text, combo_timer

    if combo_text and combo_timer > 0:
        alpha = min(255, combo_timer * 8)  # 文字淡出效果
        text_surf = font.render(combo_text, True, (255, 215, 0))  # 金色文字
        text_surf.set_alpha(alpha)

        # 文字位置在屏幕中央偏上
        text_rect = text_surf.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 3))
        screen.blit(text_surf, text_rect)

        combo_timer -= 1


def check_interspersed_elimination():
    """检查是否有可穿插消除的三张相同卡片"""
    counts = {}
    for card in slots:
        if card in counts:
            counts[card] += 1
        else:
            counts[card] = 1

    eliminated = False
    for card_type, count in counts.items():
        if count >= 3:
            # 找到要消除的卡片位置并添加特效
            eliminated_indices = []
            eliminated_count = 0

            # 记录要消除的卡片索引
            for i, card in enumerate(slots):
                if card == card_type and eliminated_count < 3:
                    eliminated_indices.append(i)
                    eliminated_count += 1

            # 从后向前处理，避免索引变化
            eliminated_indices.sort(reverse=True)
            for i in eliminated_indices:
                x = SLOT_LEFT + i * (CARD_WIDTH + 5)
                y = SLOT_TOP
                add_elim_effect(x, y, card_type)

            # 移除三张相同的卡片
            new_slots = []
            for i, card in enumerate(slots):
                if i not in eliminated_indices:
                    new_slots.append(card)
            slots[:] = new_slots

            eliminated = True

    # 如果有消除，显示连击文字
    if eliminated:
        global combo_text, combo_timer
        combo_text = "三连消除!"
        combo_timer = 30

    return eliminated


# 初始化卡片堆
grid = []
for row in range(GRID_ROWS):
    grid_row = []
    for col in range(GRID_COLS):
        layers = random.randint(3, 5)
        max_card_type = len(card_images) - 1 if card_images else len(COLORS) - 1
        stack = [random.randint(0, max_card_type) for _ in range(layers)]
        stack += [stack[-1]] * (3 - layers % 3) if layers % 3 != 0 else []
        grid_row.append(stack)
    grid.append(grid_row)

# 主循环
clock = pygame.time.Clock()
running = True

while running:
    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN and not game_over and not is_moving:
            x, y = pygame.mouse.get_pos()
            # 检查是否点击道具按钮
            if (
                    not prop_used
                    and BUTTON_X <= x <= BUTTON_X + BUTTON_WIDTH
                    and BUTTON_Y <= y <= BUTTON_Y + BUTTON_HEIGHT
                    and len(slots) > 0
            ):
                # 记录被移除卡片的位置和类型
                removed_card = slots[-1]
                x_pos = SLOT_LEFT + (len(slots) - 1) * (CARD_WIDTH + 5)
                y_pos = SLOT_TOP

                slots.pop()  # 移除卡槽里最后一张卡片
                prop_used = True  # 道具已使用

                # 为被移除的卡片添加消除效果
                add_elim_effect(x_pos, y_pos, removed_card)
            else:
                # 计算点击位置
                grid_col = (x - GRID_LEFT) // (CARD_WIDTH + SPACING)
                grid_row = (y - GRID_TOP) // (CARD_HEIGHT + SPACING)
                # 检查点击范围
                if 0 <= grid_row < GRID_ROWS and 0 <= grid_col < GRID_COLS:
                    if len(grid[grid_row][grid_col]) > 0:
                        # 检查槽位是否已满（改为7块）
                        if len(slots) >= SLOT_COLS:
                            game_over = True
                            continue

                        # 取出顶层卡片
                        card = grid[grid_row][grid_col].pop()
                        # 设置移动动画
                        moving_card = card
                        moving_card_x = GRID_LEFT + grid_col * (CARD_WIDTH + SPACING)
                        moving_card_y = GRID_TOP + grid_row * (CARD_HEIGHT + SPACING) - (
                                len(grid[grid_row][grid_col]) * 5)
                        target_x = SLOT_LEFT + len(slots) * (CARD_WIDTH + 5)
                        target_y = SLOT_TOP
                        is_moving = True  # 开始移动，设置标志位为True
        elif event.type == pygame.MOUSEMOTION:
            x, y = event.pos
            if (
                    not prop_used
                    and BUTTON_X <= x <= BUTTON_X + BUTTON_WIDTH
                    and BUTTON_Y <= y <= BUTTON_Y + BUTTON_HEIGHT
            ):
                button_hover = True
            else:
                button_hover = False

    # 处理移动动画
    if moving_card is not None:
        dx = target_x - moving_card_x
        dy = target_y - moving_card_y
        if abs(dx) < move_speed:
            moving_card_x = target_x
        elif dx > 0:
            moving_card_x += move_speed
        else:
            moving_card_x -= move_speed

        if abs(dy) < move_speed:
            moving_card_y = target_y
        elif dy > 0:
            moving_card_y += move_speed
        else:
            moving_card_y -= move_speed

        if moving_card_x == target_x and moving_card_y == target_y:
            slots.append(moving_card)
            # 检查穿插消除
            if check_interspersed_elimination():
                score += 1
            # 再次检查槽位是否已满
            if len(slots) >= SLOT_COLS:
                game_over = True
            # 检查胜利条件
            if check_victory():
                game_won = True
                game_over = True
            moving_card = None
            is_moving = False  # 移动结束，设置标志位为False

    # 更新特效
    update_elim_effects()
    update_particles()

    # 绘制界面
    if background_img:
        screen.blit(background_img, (0, 0))
    else:
        screen.fill(BG_COLOR)

    # 绘制卡片堆
    for row in range(GRID_ROWS):
        for col in range(GRID_COLS):
            x = GRID_LEFT + col * (CARD_WIDTH + SPACING)
            y = GRID_TOP + row * (CARD_HEIGHT + SPACING)
            stack = grid[row][col]
            for i, card_type in enumerate(stack):
                offset = i * 5  # 堆叠偏移量
                if card_images:
                    screen.blit(card_images[card_type], (x, y - offset))
                else:
                    pygame.draw.rect(screen, COLORS[card_type], (x, y - offset, CARD_WIDTH, CARD_HEIGHT))

    # 绘制槽位背景
    if slot_bg_img:
        screen.blit(slot_bg_img, (SLOT_LEFT - 10, SLOT_TOP - 10))
    else:
        pygame.draw.rect(screen, (200, 200, 200),
                         (SLOT_LEFT - 5, SLOT_TOP - 5,
                          slot_width + 10, SLOT_HEIGHT + 10),
                         border_radius=10)

    # 绘制槽位中的卡片
    for i, card in enumerate(slots):
        x = SLOT_LEFT + i * (CARD_WIDTH + 5)
        if card_images:
            screen.blit(card_images[card], (x, SLOT_TOP))
        else:
            pygame.draw.rect(screen, COLORS[card], (x, SLOT_TOP, CARD_WIDTH, CARD_HEIGHT))

    # 绘制移动中的卡片
    if moving_card is not None:
        if card_images:
            screen.blit(card_images[moving_card], (moving_card_x, moving_card_y))
        else:
            pygame.draw.rect(screen, COLORS[moving_card], (moving_card_x, moving_card_y, CARD_WIDTH, CARD_HEIGHT))

    # 绘制道具按钮
    button_color = BUTTON_HOVER_COLOR if button_hover else BUTTON_COLOR
    pygame.draw.rect(screen, button_color, (BUTTON_X, BUTTON_Y, BUTTON_WIDTH, BUTTON_HEIGHT))
    text = font.render("消除一张卡片", True, (255, 255, 255))
    text_rect = text.get_rect(center=(BUTTON_X + BUTTON_WIDTH // 2, BUTTON_Y + BUTTON_HEIGHT // 2))
    screen.blit(text, text_rect)

    # 绘制状态信息
    text = font.render(f"分数: {score}", True, (0, 0, 0))
    screen.blit(text, (20, 20))

    # 绘制槽位容量提示
    capacity_text = font.render(f"{len(slots)}/{SLOT_COLS}", True, (100, 100, 100))
    screen.blit(capacity_text, (SCREEN_WIDTH - 60, 20))

    # 绘制特效
    draw_elim_effects()
    draw_particles()
    draw_combo_text()

    # 绘制游戏结束信息
    if game_over:
        game_over_font = pygame.font.Font(None, 48)
        text = game_over_font.render("胜利!" if game_won else "游戏结束!",
                                     True, (0, 200, 0) if game_won else (200, 0, 0))
        screen.blit(text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT // 2 - 40))

        restart_text = font.render("按任意键重新开始", True, (0, 0, 0))
        screen.blit(restart_text, (SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2 + 20))

        # 处理重新开始
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:
                # 重置游戏状态
                slots = []
                score = 0
                game_over = False
                game_won = False
                prop_used = False

                # 重新初始化卡片堆
                grid = []
                for row in range(GRID_ROWS):
                    grid_row = []
                    for col in range(GRID_COLS):
                        layers = random.randint(3, 5)
                        max_card_type = len(card_images) - 1 if card_images else len(COLORS) - 1
                        stack = [random.randint(0, max_card_type) for _ in range(layers)]
                        stack += [stack[-1]] * (3 - layers % 3) if layers % 3 != 0 else []
                        grid_row.append(stack)
                    grid.append(grid_row)

    pygame.display.flip()
    clock.tick(60)  # 提高帧率使动画更流畅

pygame.quit()